//
//  WmcEncryption.swift
//  YPWatermarkCamera
//
//  Created by 周诗松 on 2022/3/30.
//

import Foundation
import SwCrypt

class WmcEncryption {
    // Internal

    static var share: WmcEncryption = {
        let manager = WmcEncryption()
        return manager
    }()

    static func encode(param: [String: Any]) -> String? {
        guard let aesKey = WmcEncryption.share.aesKey, let salt = WmcEncryption.share.salt else { return nil }
        
        guard let jsonData = try? JSONSerialization.data(withJSONObject: param, options: .prettyPrinted) else { return nil }

        guard let jsonString = String(data: jsonData, encoding: .utf8) else { return nil }

        let data = jsonString.data(using: .utf8)!
        let nonceStr = WmcEncryption.share.randomString(length: 12)

        if let value = try? CC.cryptAuth(.encrypt, blockMode: .gcm, algorithm: .aes, data: data, aData: salt, key: aesKey, iv: nonceStr.data(using: .utf8)!, tagLength: 16) {
            return nonceStr + value.base64EncodedString()
        } else {
            return ""
        }
    }

    static func decode(_ str: String) -> Any? {
        guard let aesKey = WmcEncryption.share.aesKey, let salt = WmcEncryption.share.salt else { return nil }
        
        let index = str.index(str.startIndex, offsetBy: 12)
        let ivStr = str[str.startIndex ..< index]
        // TODO: 废弃api需要更换
        let dataStr = str.substring(from: index)

        guard let data = Data(base64Encoded: dataStr) else { return nil }

        if let value = try? CC.cryptAuth(.decrypt, blockMode: .gcm, algorithm: .aes, data: data, aData: salt, key: aesKey, iv: ivStr.data(using: .utf8)!, tagLength: 16) {
            if let jsonData = try? JSONSerialization.jsonObject(with: value, options: .mutableContainers) {
                if let array = jsonData as? [[String: Any]] {
                    return array
                }

                return jsonData as? [String: Any]
            } else {
                return nil
            }

        } else {
            return nil
        }
    }

    // Private

    private lazy var aesKey: Data? = {
        let environmentType = YPWmcManager.shared.environmentType
        var data: Data?
        if environmentType == .develop || environmentType == .test {
            data = "dEtH6fJheb1PnoR7Ordy4TJBPb1fgE6e".data(using: .utf8)!
        } else if environmentType == .pre_release {
            data = "g5GzEQiSLFAWgxotSyWRqDUg1t0fvNRY".data(using: .utf8)!
        } else if environmentType == .release {
            data = "g5GzEQiSLFAWgxotSyWRqDUg1t0fvNRY".data(using: .utf8)!
        }
        return data
    }()

    private lazy var salt: Data? = {
        let environmentType = YPWmcManager.shared.environmentType
        var data: Data?
        if environmentType == .develop || environmentType == .test {
            data = "Z5s4qNPvI^[eTPzR".data(using: .utf8)!
        } else if environmentType == .pre_release {
            data = "vf2DofwbQPx1YgRN".data(using: .utf8)!
        } else if environmentType == .release {
            data = "vf2DofwbQPx1YgRN".data(using: .utf8)!
        }
        return data
    }()

    private func randomString(length: Int) -> String {
        let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        return String((0 ..< length).map { _ in letters.randomElement()! })
    }
}
